win32 theme: Add a way to query border of theme parts
authorBenjamin Otte <otte@gnome.org>
Mon, 15 Feb 2016 05:50:22 +0000 (06:50 +0100)
committerBenjamin Otte <otte@redhat.com>
Wed, 17 Feb 2016 03:49:26 +0000 (04:49 +0100)
gtk/gtkcssnumbervalue.c
gtk/gtkcsswin32sizevalue.c
gtk/gtkwin32draw.c
gtk/gtkwin32drawprivate.h
gtk/gtkwin32theme.c
gtk/gtkwin32themeprivate.h

index e8256c0cf784685ea6765a4e90ff04f3cc5bda4c..54e1d1c006511cd21761a9e91ecd4dbf74168dbe 100644 (file)
@@ -133,7 +133,11 @@ gtk_css_number_value_can_parse (GtkCssParser *parser)
       || _gtk_css_parser_has_prefix (parser, "calc")
       || _gtk_css_parser_has_prefix (parser, "-gtk-win32-size")
       || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width")
-      || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height");
+      || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height")
+      || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-top")
+      || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-left")
+      || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-bottom")
+      || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-right");
 }
 
 GtkCssValue *
@@ -144,7 +148,11 @@ _gtk_css_number_value_parse (GtkCssParser           *parser,
     return gtk_css_calc_value_parse (parser, flags);
   if (_gtk_css_parser_has_prefix (parser, "-gtk-win32-size") ||
       _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width") ||
-      _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height"))
+      _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height") ||
+      _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-top") ||
+      _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-left") ||
+      _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-bottom") ||
+      _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-right"))
     return gtk_css_win32_size_value_parse (parser, flags);
 
   return gtk_css_dimension_value_parse (parser, flags);
index 7c35d37902d2f0d40f717e19042748f404471270..9497c9c7f596b3308b812ce7faea5859d3f4ec3d 100644 (file)
 typedef enum {
   GTK_WIN32_SIZE,
   GTK_WIN32_PART_WIDTH,
-  GTK_WIN32_PART_HEIGHT
+  GTK_WIN32_PART_HEIGHT,
+  GTK_WIN32_PART_BORDER_TOP,
+  GTK_WIN32_PART_BORDER_RIGHT,
+  GTK_WIN32_PART_BORDER_BOTTOM,
+  GTK_WIN32_PART_BORDER_LEFT
 } GtkWin32SizeType;
 
 static const char *css_value_names[] = {
   "-gtk-win32-size(",
   "-gtk-win32-part-width(",
-  "-gtk-win32-part-height("
+  "-gtk-win32-part-height(",
+  "-gtk-win32-part-border-top(",
+  "-gtk-win32-part-border-right(",
+  "-gtk-win32-part-border-bottom(",
+  "-gtk-win32-part-border-left("
 };
 
 struct _GtkCssValue {
@@ -63,6 +71,7 @@ gtk_css_value_win32_size_free (GtkCssValue *value)
 static int
 gtk_css_value_win32_compute_size (const GtkCssValue *value)
 {
+  GtkBorder border;
   int size;
 
   switch (value->type)
@@ -78,6 +87,26 @@ gtk_css_value_win32_compute_size (const GtkCssValue *value)
       gtk_win32_theme_get_part_size (value->theme, value->val.part.part, value->val.part.state, NULL, &size);
       break;
 
+    case GTK_WIN32_PART_BORDER_TOP:
+      gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border);
+      size = border.top;
+      break;
+
+    case GTK_WIN32_PART_BORDER_RIGHT:
+      gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border);
+      size = border.right;
+      break;
+
+    case GTK_WIN32_PART_BORDER_BOTTOM:
+      gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border);
+      size = border.bottom;
+      break;
+
+    case GTK_WIN32_PART_BORDER_LEFT:
+      gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border);
+      size = border.left;
+      break;
+
     default:
       g_assert_not_reached ();
       return 0;
@@ -139,6 +168,10 @@ gtk_css_value_win32_size_print (const GtkCssValue *value,
 
     case GTK_WIN32_PART_WIDTH:
     case GTK_WIN32_PART_HEIGHT:
+    case GTK_WIN32_PART_BORDER_TOP:
+    case GTK_WIN32_PART_BORDER_RIGHT:
+    case GTK_WIN32_PART_BORDER_BOTTOM:
+    case GTK_WIN32_PART_BORDER_LEFT:
       g_string_append_printf (string, ", %d, %d", value->val.part.part, value->val.part.state);
       break;
 
@@ -317,6 +350,10 @@ gtk_css_win32_size_value_parse (GtkCssParser           *parser,
 
     case GTK_WIN32_PART_WIDTH:
     case GTK_WIN32_PART_HEIGHT:
+    case GTK_WIN32_PART_BORDER_TOP:
+    case GTK_WIN32_PART_BORDER_RIGHT:
+    case GTK_WIN32_PART_BORDER_BOTTOM:
+    case GTK_WIN32_PART_BORDER_LEFT:
       result = gtk_css_win32_size_value_parse_part_size (result, parser);
       break;
 
index 1c761f2c3165d362834407bdf88454226eae0ae4..4a28f115fa1c26be7a314b1068ac5ac0b37d5ef5 100644 (file)
@@ -86,6 +86,7 @@ struct _GtkWin32ThemePart {
   const char *class_name;
   gint        part;
   gint        size;
+  GtkBorder   margins;
   void        (* draw_func)             (cairo_t        *cr,
                                          int             part,
                                          int             state,
@@ -94,9 +95,9 @@ struct _GtkWin32ThemePart {
 };
 
 static GtkWin32ThemePart theme_parts[] = {
-  { "button", 1,  0, draw_button },
-  { "button", 2, 13, draw_radio },
-  { "button", 3, 13, draw_check }
+  { "button", 1,  0, { 3, 3, 3, 3 }, draw_button },
+  { "button", 2, 13, { 0, 0, 0, 0 }, draw_radio },
+  { "button", 3, 13, { 0, 0, 0, 0 }, draw_check }
 };
 
 static const GtkWin32ThemePart *
@@ -158,6 +159,26 @@ gtk_win32_get_theme_part_size (const char *class_name,
     }
 }
 
+void
+gtk_win32_get_theme_margins (const char     *class_name,
+                             int             part,
+                             int             state,
+                             GtkBorder      *out_margins)
+{
+  const GtkWin32ThemePart *theme_part;
+
+  theme_part = get_theme_part (class_name, part);
+
+  if (theme_part)
+    {
+      *out_margins = theme_part->margins;
+    }
+  else
+    {
+      out_margins->top = out_margins->bottom = out_margins->left = out_margins->right = 0;
+    }
+}
+
 struct {
   const char *name;
   GdkRGBA rgba;
index f8a11ca2ea1ee46eeedc36c0bd2ed5a7c5b95740..b2f339ad9f495da98814d0b204e218bf8235a743 100644 (file)
@@ -21,6 +21,8 @@
 #include <gdk/gdk.h>
 #include <cairo.h>
 
+#include <gtk/gtkborder.h>
+
 G_BEGIN_DECLS
 
 enum {
@@ -68,6 +70,10 @@ void                    gtk_win32_get_theme_part_size           (const char
                                                                  int             state,
                                                                  int            *width,
                                                                  int            *height);
+void                    gtk_win32_get_theme_margins             (const char     *class_name,
+                                                                 int             part,
+                                                                 int             state,
+                                                                 GtkBorder      *out_margins);
 
 void                    gtk_win32_get_sys_color                 (gint            id,
                                                                  GdkRGBA        *color);
index dced7c7f102b57af5ec6e3af9f75ce2933029bbd..dadc910cc2a45f5b916a7225654020af5062c9ce 100644 (file)
@@ -64,6 +64,12 @@ typedef HRESULT (FAR PASCAL *GetThemePartSizeFunc)          (HTHEME hTheme,
                                                             RECT *prc,
                                                             int eSize,
                                                             SIZE *psz);
+typedef HRESULT (FAR PASCAL *GetThemeBackgroundExtentFunc)  (HTHEME hTheme,
+                                                            HDC hdc,
+                                                            int iPartId,
+                                                            int iStateId,
+                                                             const RECT *pContentRect,
+                                                             RECT *pExtentRect);
 
 static GetThemeSysFontFunc get_theme_sys_font = NULL;
 static GetThemeSysColorFunc GetThemeSysColor = NULL;
@@ -77,6 +83,7 @@ static IsAppThemedFunc is_app_themed = NULL;
 static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent = NULL;
 static DrawThemeParentBackgroundFunc draw_theme_parent_background = NULL;
 static GetThemePartSizeFunc GetThemePartSize = NULL;
+static GetThemeBackgroundExtentFunc GetThemeBackgroundExtent = NULL;
 
 #endif
 
@@ -212,6 +219,7 @@ gtk_win32_theme_init (void)
       is_theme_partially_transparent = (IsThemeBackgroundPartiallyTransparentFunc) GetProcAddress (uxtheme_dll, "IsThemeBackgroundPartiallyTransparent");
       draw_theme_parent_background = (DrawThemeParentBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeParentBackground");
       GetThemePartSize = (GetThemePartSizeFunc) GetProcAddress (uxtheme_dll, "GetThemePartSize");
+      GetThemeBackgroundExtent = (GetThemeBackgroundExtentFunc) GetProcAddress (uxtheme_dll, "GetThemeBackgroundExtent");
     }
 
   if (is_app_themed && is_theme_active)
@@ -387,6 +395,43 @@ gtk_win32_theme_create_surface (GtkWin32Theme *theme,
   return surface;
 }
 
+void
+gtk_win32_theme_get_part_border (GtkWin32Theme  *theme,
+                                 int             part,
+                                 int             state,
+                                 GtkBorder      *out_border)
+{
+#ifdef G_OS_WIN32
+  HTHEME htheme = gtk_win32_theme_get_htheme (theme);
+  RECT content, extent;
+  HDC hdc;
+  HRESULT res;
+
+  if (use_xp_theme && GetThemeBackgroundExtent != NULL && htheme != NULL)
+    {
+      /* According to Wine source code, these values don't matter
+       * because uxtheme.dll deals with margins internally. */
+      content.left = content.top = 0;
+      content.right = content.bottom = 100;
+
+      hdc = GetDC (NULL);
+      res = GetThemeBackgroundExtent (htheme, hdc, part, state, &content, &extent);
+      ReleaseDC (NULL, hdc);
+
+      if (SUCCEEDED (res))
+        {
+          out_border->top = content.top - extent.top;
+          out_border->left = content.left - extent.left;
+          out_border->bottom = extent.bottom - content.bottom;
+          out_border->right = extent.right - content.right;
+          return;
+        }
+    }
+#endif
+
+  gtk_win32_get_theme_margins (theme->class_name, part, state, out_border);
+}
+
 void
 gtk_win32_theme_get_part_size (GtkWin32Theme  *theme,
                                int             part,
index b03bea835ee357f9dfb995311b37c123fb34ba82..9ea7777366b7ab09943534b8961945f813e0a3e1 100644 (file)
@@ -49,6 +49,10 @@ cairo_surface_t *       gtk_win32_theme_create_surface  (GtkWin32Theme *theme,
                                                         int           *x_offs_out,
                                                         int           *y_offs_out);
 
+void                    gtk_win32_theme_get_part_border (GtkWin32Theme  *theme,
+                                                         int             part,
+                                                         int             state,
+                                                         GtkBorder      *out_border);
 void                    gtk_win32_theme_get_part_size   (GtkWin32Theme  *theme,
                                                          int             part,
                                                          int             state,